package com.zjb.demo.system.service;

import com.zjb.demo.common.config.AppConfig;
import com.zjb.demo.common.constant.CacheConstants;
import com.zjb.demo.common.constant.Constants;
import com.zjb.demo.common.exception.UserPasswordRetryLimitExceedException;
import com.zjb.demo.common.util.SecurityUtils;
import com.zjb.demo.framework.manager.AsyncManager;
import com.zjb.demo.framework.security.AuthenticationContextHolder;
import com.zjb.demo.system.domain.User;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.cache.CacheService;
import org.noear.solon.i18n.I18nUtil;

/**
 * 登录密码方法
 *
 * @author 庄佳彬
 * @since 2023/12/25 20:25
 */
@Component
public class SysPasswordService {
    @Inject
    private CacheService cacheService;

    @Inject
    private AsyncManager manager;

    @Inject
    private AppConfig config;

    private String getCacheKey(String username) {
        return CacheConstants.PWD_ERR_CNT_KEY + username;
    }

    /**
     * 验证用户密码是否正确
     *
     * @param user 待验证的用户
     */
    public void validate(User user) {
        // 获取当前认证信息
        var authentication = AuthenticationContextHolder.getAuthentication();
        // 获取用户名
        var username = authentication.getUsername();
        // 获取密码
        var password = authentication.getPassword();

        // 从缓存中获取重试次数，如果缓存为空，则设置重试次数为0
        var retryCount = cacheService.get(getCacheKey(username), Integer.class);
        if (retryCount == null) {
            retryCount = 0;
        }

        // 如果重试次数超过最大重试次数，则锁定用户账号并抛出异常
        if (retryCount >= config.getMaxRetryCount()) {
            manager.saveLoginInfo(username, Constants.ERROR,
                    I18nUtil.getMessage("user.password.retry.limit.exceed", new Object[]{config.getMaxRetryCount(), config.getLockTime()}));
            throw new UserPasswordRetryLimitExceedException();
        }

        // 验证密码是否匹配
        if (!matches(user, password)) {
            // 重试次数加1
            retryCount++;
            manager.saveLoginInfo(username, Constants.ERROR,
                    I18nUtil.getMessage("user.password.retry.limit.count", new Object[]{retryCount}));

            // 将重试次数存入缓存，过期时间为主机时间加上锁定时间的分钟数
            cacheService.store(getCacheKey(username), retryCount, config.getLockTime() * 60);
            throw new UserPasswordRetryLimitExceedException();
        } else {
            // 清除登录记录缓存
            cleanLoginRecordCache(username);
        }
    }


    /**
     * 判断给定的用户和密码是否匹配
     *
     * @param user        待匹配的用户对象
     * @param rawPassword 待匹配的密码字符串
     * @return 如果密码匹配，则返回true；否则返回false
     */
    public boolean matches(User user, String rawPassword) {
        return SecurityUtils.matchesPassword(user.getPassword(), rawPassword);
    }

    /**
     * 清除登录记录缓存
     *
     * @param username 用户名
     */
    public void cleanLoginRecordCache(String username) {
        cacheService.remove(getCacheKey(username));
    }


}
